package core

import (
	"encoding/json"
	"flag"
	"fmt"
	"goweb/web/global"
	"os"

	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
)

func Viper(path ...string) *viper.Viper {
	// 配置文件名称
	var config string

	// 判断参数
	if len(path) == 0 {
		// 优先级: 命令行 > 环境变量 > 默认值
		// 1.1 从命令行中获取参数
		/**
		p *string: 接收参数的地址
		name string: 命令行参数，如 -c , -u
		value string: 默认值
		usage string: 命令行提示信息
		*/
		flag.StringVar(&config, "c", "", "choose config file.")
		flag.Parse()

		if config == "" {
			// 1.2 从环境变量中获取 configEnv 配置
			if configEnv := os.Getenv(global.ConfigEnv); configEnv != "" {
				config = configEnv
				fmt.Printf("您正在使用CONFIG环境变量,config的路径为%v\n", config)
			} else {
				// 1.3 从系统配置中获取参数
				config = global.ConfigFile
				fmt.Printf("您正在使用config的默认值,config的路径为%v\n", config)
			}
		} else {
			config = path[0]
			fmt.Printf("您正在使用参数变量,config的路径为%v\n", config)
		}
	}

	v := viper.New()
	v.SetConfigName(config) // name of config file (without extension)
	v.SetConfigType("yaml") // REQUIRED if the config file does not have the extension in the name
	// v.AddConfigPath("/etc/appname/")  // path to look for the config file in
	// v.AddConfigPath("$HOME/.appname") // call multiple times to add many search paths

	// 当前路径
	v.AddConfigPath(".") // optionally look for config in the working directory
	if err := v.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); ok {
			// Config file not found; ignore error if desired
			fmt.Printf("the config file does not exist: %s \n", err)
		} else {
			// Config file was found but another error was produced
			fmt.Printf("Fatal error config file: %s \n", err)
		}
	}

	// Config file found and successfully parsed
	// 开启自动拉取配置并刷新环境变量
	v.OnConfigChange(func(e fsnotify.Event) {
		// 当配置更新时执行如下：
		if err := v.Unmarshal(&global.Config); err != nil {
			fmt.Printf("配置文件解析错误: %s", err.Error())
		}
		fmt.Println("Config file changed:", e.Name)
	})
	// 监听配置变化
	v.WatchConfig()

	// 初次运行时执行：将数据解析到 global.Config结构体中
	if err := v.Unmarshal(&global.Config); err != nil {
		fmt.Printf("配置文件解析错误: %s", err.Error())
	}

	b, _ := json.Marshal(global.Config)
	fmt.Printf("global config data: %s \n", string(b))
	return v
}
